import { textWrap } from "./utils";

export enum SourceType {
  FONT = 1
}
export interface IBaseStyle {
  index?: number;
  width?: number;
  height?: number;
  x?: number;
  y?: number;
  editable?: boolean
}
export interface IImageStyle extends IBaseStyle {
  type: "IMAGE";
  src: string;
}
export interface ITextStyle extends IBaseStyle {
  type: "TEXT";
  content: string;
  fontSize?: number;
  fontFamily?: string;
  algin?: "center" | "left" | "right";
  color?: string;
}
export type IPosterStyle = IImageStyle | ITextStyle;
export type IPosterSource = {
  name: string;
  type: SourceType;
  path: string;
};
export interface IPosterTemplate {
  /**
   * 海报可视大小,超出可视大小的内容将不会出现在生成的图片上
   */
  view: {
    width: number;
    height: number;
  };
  /**
   * 海报中使用到的字体资源,字体需要先预加载之后才会生效
   */
  source: IPosterSource[];
  elements: IPosterStyle[];
}
export async function templateParser(template: IPosterTemplate): Promise<string> {
  const canvas = createViewCanvas(template.view);
  await loadSource(template.source);
  await drawElement(canvas.getContext("2d") as CanvasRenderingContext2D, template.elements);
  return canvas.toDataURL();
}
function createViewCanvas(view: { width: number; height: number; }) {
  const result = document.createElement("canvas");
  result.width = view.width;
  result.height = view.height;

  return result;
}
function loadSource(source: IPosterSource[]) { }

async function drawElement(ctx: CanvasRenderingContext2D, elements: IPosterStyle[]) {
  const list = elements.slice().sort((a, b) => (a.index || 0) - (b.index || 0));
  for (const element of list) {
    const command = getDrawCommand(element);
    await command(ctx);
  }
}
function getDrawCommand(element: IPosterStyle) {
  switch (element.type) {
    case "IMAGE":
      return (ctx: CanvasRenderingContext2D) => drawImage(ctx, element);
    case "TEXT":
      return (ctx: CanvasRenderingContext2D) => drawText(ctx, element);
  }
}

async function drawImage(ctx: CanvasRenderingContext2D, element: IImageStyle) {
  const { x = 0, y = 0, width, height } = element;
  const img = await loadImg(element.src);
  const dw = width || img.width;
  const dh = height || img.height;
  ctx.drawImage(img, x, y, dw, dh);
}

async function drawText(ctx: CanvasRenderingContext2D, element: ITextStyle) {
  const { content, x = 0, y = 0, fontSize = 12, fontFamily, algin = "left", width, height, color = "#000000" } = element;
  ctx.save();
  ctx.font = `${fontSize}px ${fontFamily}`;
  ctx.textBaseline = "hanging";
  ctx.fillStyle = color;
  ctx.textAlign = algin;
  const strArr = textWrap(ctx, content, width);
  for (let i = 0; i < strArr.length; i++) {
    const str = strArr[i];
    let sx: number;
    if (algin === "center") {
      sx = x + (width || 0) / 2;
    } else if (algin === "right") {
      sx = x + (width || 0);
    } else {
      sx = x;
    }
    ctx.fillText(str, sx, y + i * fontSize);
  }
  ctx.restore();
}
function loadImg(url: string): Promise<HTMLImageElement> {
  return new Promise((resolve, reject) => {
    const img = new Image();
    img.crossOrigin = "anonymous";
    img.src = url;
    img.onload = () => {
      resolve(img);
    };
    img.onerror = reject;
  });
}

